"""Books API endpoints for AncientSeeker.

Handles book management, search, and metadata operations.
"""

from __future__ import annotations

from typing import List, Optional
from pathlib import Path
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session

from app.database import get_db
from app.utils.auth import get_current_active_user, get_current_admin_user
from app.models.user import User
from app.schemas.book import (
    BookOut,
    BookDetail,
    BookSearchResult,
    BookCategory,
    BookCreate,
    BookUpdate,
)
from app.services.book_service import book_service


router = APIRouter()


@router.get("/", response_model=BookSearchResult)
async def get_books(
    page: int = Query(1, ge=1),
    page_size: int = Query(20, ge=1, le=100),
    category: Optional[str] = Query(None),
    dynasty: Optional[str] = Query(None),
    difficulty: Optional[str] = Query(None),
    keyword: Optional[str] = Query(None),
    db: Session = Depends(get_db),
):
    """获取书籍列表（支持分页和筛选）"""
    try:
        return book_service.get_books(
            db=db,
            page=page,
            page_size=page_size,
            category=category,
            dynasty=dynasty,
            difficulty=difficulty,
            keyword=keyword,
        )
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取书籍列表失败: {str(e)}")


@router.get("/{book_id}", response_model=BookDetail)
async def get_book_detail(book_id: int, db: Session = Depends(get_db)):
    """获取书籍详情"""
    try:
        book = book_service.get_book_by_id(db, book_id)
        if not book:
            raise HTTPException(status_code=404, detail="书籍不存在")

        # Repair legacy or invalid cover path on the fly (does not necessarily persist)
        images_dir = Path(__file__).resolve().parents[3] / "backend" / "data" / "images"
        cover_value = getattr(book, "cover", None)
        effective_cover = (
            cover_value if isinstance(cover_value, str) else (cover_value or None)
        )
        if effective_cover and isinstance(effective_cover, str):
            invalid = ("/" in effective_cover) or (
                not (images_dir / effective_cover).exists()
            )
            if invalid:
                candidate = f"{book.book_id}_cover.png"
                if (images_dir / candidate).exists():
                    effective_cover = candidate
                else:
                    for alt in [
                        f"{book.book_id}_cover.jpg",
                        f"{book.book_id}-cover.png",
                        f"{book.book_id}-cover.jpg",
                    ]:
                        if (images_dir / alt).exists():
                            effective_cover = alt
                            break
        return {
            "id": book.id,
            "book_id": book.book_id,
            "title": book.title,
            "subtitle": book.subtitle,
            "author": book.author,
            "dynasty": book.dynasty,
            "category": book.category,
            "description": book.description,
            "total_chapters": book.total_chapters,
            "total_characters": book.total_characters,
            "cover": effective_cover,
            "cover_url": (
                f"/static/{effective_cover}"
                if (effective_cover and isinstance(effective_cover, str))
                else None
            ),
            "difficulty": book.difficulty,
            "language": book.language,
            "tags": book.tags,
            "content": book.content,
            "created_at": book.created_at,
            "updated_at": book.updated_at,
        }

    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取书籍详情失败: {str(e)}")


@router.post("/", response_model=BookOut)
async def create_book(
    book_data: BookCreate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_admin_user),
):
    """创建新书籍（仅管理员）"""
    try:
        # 检查book_id是否已存在
        existing_book = book_service.get_book_by_book_id(db, book_data.book_id)
        if existing_book:
            raise HTTPException(status_code=400, detail="书籍ID已存在")

        book = book_service.create_book(db, book_data)
        if not book:
            raise HTTPException(status_code=500, detail="创建书籍失败")

        return {
            "id": book.id,
            "book_id": book.book_id,
            "title": book.title,
            "author": book.author,
            "dynasty": book.dynasty,
            "category": book.category,
            "description": book.description,
            "tags": book.tags,
            "created_at": book.created_at,
            "updated_at": book.updated_at,
        }

    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"创建书籍失败: {str(e)}")


@router.put("/{book_id}", response_model=BookOut)
async def update_book(
    book_id: int,
    book_update: BookUpdate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_admin_user),
):
    """更新书籍信息（仅管理员）"""
    try:
        book = book_service.update_book(db, book_id, book_update)
        if not book:
            raise HTTPException(status_code=404, detail="书籍不存在或更新失败")

        return {
            "id": book.id,
            "book_id": book.book_id,
            "title": book.title,
            "author": book.author,
            "dynasty": book.dynasty,
            "category": book.category,
            "description": book.description,
            "tags": book.tags,
            "created_at": book.created_at,
            "updated_at": book.updated_at,
        }

    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"更新书籍失败: {str(e)}")


@router.delete("/{book_id}")
async def delete_book(
    book_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_admin_user),
):
    """删除书籍（仅管理员）"""
    try:
        success = book_service.delete_book(db, book_id)
        if not success:
            raise HTTPException(status_code=404, detail="书籍不存在或删除失败")

        return {"message": "书籍删除成功"}

    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"删除书籍失败: {str(e)}")


@router.get("/search/", response_model=BookSearchResult)
async def search_books(
    keyword: str = Query(..., min_length=1),
    page: int = Query(1, ge=1),
    page_size: int = Query(20, ge=1, le=100),
    db: Session = Depends(get_db),
):
    """搜索书籍（全文检索）"""
    try:
        return book_service.search_books(
            db=db, keyword=keyword, page=page, page_size=page_size
        )
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"搜索书籍失败: {str(e)}")


@router.get("/categories/", response_model=List[BookCategory])
async def get_book_categories(db: Session = Depends(get_db)):
    """获取书籍分类统计"""
    try:
        return book_service.get_categories(db)
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取分类失败: {str(e)}")


@router.post("/load-from-json")
async def load_books_from_json(
    overwrite: bool = Query(False, description="是否覆盖已存在的书籍"),
    directory: Optional[str] = Query(
        None, description="自定义书籍JSON目录（绝对或相对路径）"
    ),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_admin_user),
):
    """从JSON文件加载/更新书籍数据（仅管理员）。

    支持：
      - overwrite=true 覆盖已存在同 book_id 的书籍
      - directory 指定自定义目录；若未提供使用配置中的绝对目录
    返回详细统计信息。
    """
    try:
        summary = book_service.load_books_from_json(
            db, data_dir=directory, overwrite=overwrite
        )
        return {"message": "处理完成", "summary": summary}
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"加载书籍数据失败: {str(e)}")


@router.get("/{book_id}/concepts")
async def get_book_concepts(
    book_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
):
    """获取书籍的关键概念"""
    try:
        book = book_service.get_book_by_id(db, book_id)
        if not book:
            raise HTTPException(status_code=404, detail="书籍不存在")

        concepts = book_service.extract_key_concepts(book)
        return {"concepts": concepts}

    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取关键概念失败: {str(e)}")


@router.get("/{book_id}/content")
async def get_book_content(
    book_id: int,
    chapter_id: Optional[int] = Query(None),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
):
    """获取书籍内容（按章节）"""
    try:
        book = book_service.get_book_by_id(db, book_id)
        if not book:
            raise HTTPException(status_code=404, detail="书籍不存在")

        content = book_service.get_book_content_by_chapter(book, chapter_id)
        if not content:
            raise HTTPException(status_code=404, detail="内容不存在")

        return content

    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取书籍内容失败: {str(e)}")
